//
//  ViewController.m
//  1. __attribute__()
//
//  Created by lirenqiang on 2016/11/1.
//  Copyright © 2016年 1111. All rights reserved.
//
/*
    本来是要写__attribute__的，结果sunnyxx的博客是写cleanup的，也算是一个意外的收获了吧。
    下面就看mattt的博客怎么介绍__attribute__的吧。
 */



#import "ViewController.h"

//万能的Reactivce Cocoa 中的  @onExit 方法


#pragma mark -
#pragma mark 自定义的Class
#pragma mark -
@interface Sark : NSObject

@end

@implementation Sark



@end

@interface ViewController ()

@end
#define onExit(block)\
    __strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^

#pragma mark -
#pragma mark attribute的用法
#pragma mark -
// Return the square of a number
int square(int n) __attribute__((const));

//Declare the availability of a particular API
void f(void) __attribute__((availability(macosx, introduced=10.4, deprecated=10.6)));

extern int my_printf(void *my_object, const char *my_format, ...)
    __attribute__((format(printf, 2, 3)));


//Send printf-like message to stderr and exit
extern void die(const char *format, ...)
__attribute__((noreturn, format(printf, 1, 2)));


@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self test];
    
}




#pragma mark -
#pragma mark 通用函数
#pragma mark -
- (void)test
{
    NSLog(@"hello world");
    /*
     若一个作用域内有若干个cleanup的变量，他们的调用顺序是先入后出的栈式顺序
     cleanup是先于这个对象的的dealloc调用的。
     */
    onExit(block1) {
        NSLog(@"block1");
    };
    __strong NSString *string __attribute__((cleanup(stringCleanUp))) = @"sunnyxx";
    __strong Sark *sark __attribute__((cleanup(sarkCleanUp))) = [Sark new];
    NSInteger integer __attribute__((cleanup(intCleanUp))) = 1;
    
    NSRecursiveLock *aLock = [[NSRecursiveLock alloc] init];
    onExit(block2) {
      
        NSLog(@"block2");
    };
    
    NSLog(@"");
    
}




#pragma mark -
#pragma mark 基本用法
#pragma mark -
//指定一个cleanup方法，注意入参是所修饰变量的地址，类型要一样。
static void stringCleanUp(__strong NSString **string)
{
    NSLog(@"%@", *string);
}

//自定义的class
static void sarkCleanUp(__strong Sark **sark)
{
    NSLog(@"%@", *sark);
}

//基本类型
static void intCleanUp(NSInteger *integer)
{
    NSLog(@"%zd", *integer);
}



#pragma mark -
#pragma mark 进阶用法
#pragma mark -
// void(^block)(void)的指针是void(^*block)(void)
static void blockCleanUp(__strong void(^*block)(void)) {
    (*block)();
}



- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end


























